package repository

import (
	"context"
	"fmt"
	"gorm.io/gorm"
	v1 "server_go/api/v1"
	"server_go/internal/model"
)

type ArticleRepository interface {
	GetArticle(ctx context.Context, id int64) (*model.Article, error)
	GetArticleByID(ctx context.Context, id uint) (*model.Article, error)
	DeleteArticleByID(ctx context.Context, id uint) error
	CreateArticle(ctx context.Context, req v1.CreateArticleRequest) (*model.Article, error, uint)
	CreateArticleTag(ctx context.Context, tag uint, articleId uint) (*model.Article_tags, error)
	GetArticles(ctx context.Context) (*[]model.Article, error)
	GetTagIdByArticleID(ctx context.Context, articleId uint) ([]uint, error)
	GetTagsByIDs(ctx context.Context, ids []uint) ([]model.Tag, error)
	GetUserById(ctx context.Context, userId uint) (*model.Users, error)
	QueryUserByUserId(ctx context.Context, userId uint) ([]model.Article, error)
	GetArticleIDsByTagID(ctx context.Context, tagID uint) ([]uint, error)
}

func NewArticleRepository(
	repository *Repository,
) ArticleRepository {
	return &articleRepository{
		Repository: repository,
	}
}

type articleRepository struct {
	*Repository
}

func (r *articleRepository) GetArticle(ctx context.Context, id int64) (*model.Article, error) {
	var article model.Article
	return &article, nil
}

func (r *articleRepository) GetArticleByID(ctx context.Context, id uint) (*model.Article, error) {
	var article model.Article
	err := r.DB(ctx).Where("id=?", id).First(&article).Error
	if err != nil {
		return nil, err
	}
	return &article, nil
}

func (r *articleRepository) DeleteArticleByID(ctx context.Context, id uint) error {
	db := r.DB(ctx)

	return db.Transaction(func(tx *gorm.DB) error {
		// 删关系表
		if err := tx.WithContext(ctx).
			Where("article_id = ?", id).
			Delete(&model.Article_tags{}).Error; err != nil {
			return fmt.Errorf("删除文章关系表失败: %w", err)
		}

		// 删文章表
		if err := tx.WithContext(ctx).
			Where("id = ?", id).
			Delete(&model.Article{}).Error; err != nil {
			return fmt.Errorf("删除文章失败: %w", err)
		}

		return nil
	})
}

func (r *articleRepository) CreateArticle(ctx context.Context, req v1.CreateArticleRequest) (*model.Article, error, uint) {
	var article model.Article
	article.Title = req.Title
	article.Content = req.Content
	article.UserID = req.UserID
	err := r.DB(ctx).Create(&article).Error
	return &article, err, article.ID
}
func (r *articleRepository) CreateArticleTag(ctx context.Context, tag uint, articleId uint) (*model.Article_tags, error) {
	var articleTag model.Article_tags
	articleTag.ArticleID = articleId
	articleTag.TagID = tag
	err := r.DB(ctx).Create(&articleTag).Error
	return &articleTag, err
}

func (r *articleRepository) GetArticles(ctx context.Context) (*[]model.Article, error) {
	var articles []model.Article
	err := r.DB(ctx).Find(&articles).Error
	if err != nil {
		return nil, err
	}
	return &articles, nil
}

func (r *articleRepository) GetTagIdByArticleID(ctx context.Context, articleId uint) ([]uint, error) {
	var articleTag []uint
	err := r.DB(ctx).Table("article_tags").Where("article_id=?", articleId).Pluck("tag_id", &articleTag).Error
	return articleTag, err
}
func (r *articleRepository) GetArticleIDsByTagID(ctx context.Context, tagID uint) ([]uint, error) {
	var ids []uint
	err := r.DB(ctx).Table("article_tags").Where("tag_id = ?", tagID).Pluck("article_id", &ids).Error
	if err != nil {
		return nil, err
	}
	return ids, nil
}

func (r *articleRepository) GetArticleByUserId(ctx context.Context, articleId uint, userId uint) (*model.Article, error) {
	var article model.Article
	err := r.DB(ctx).Where("id=? and user_id=?", articleId, userId).First(&article).Error
	if err != nil {
		return nil, err
	}
	return &article, nil
}
func (r *articleRepository) GetTagsByIDs(ctx context.Context, ids []uint) ([]model.Tag, error) {
	var tags []model.Tag
	if err := r.DB(ctx).Where("id IN ?", ids).Find(&tags).Error; err != nil {
		return nil, err
	}
	return tags, nil
}
func (r *articleRepository) GetUserById(ctx context.Context, userId uint) (*model.Users, error) {
	var users model.Users
	err := r.DB(ctx).Where("id=?", userId).First(&users).Error
	if err != nil {
		return nil, err
	}
	return &users, nil
}

func (r *articleRepository) QueryUserByUserId(ctx context.Context, userId uint) ([]model.Article, error) {
	var article []model.Article
	err := r.DB(ctx).Where("user_id=?", userId).Find(&article).Error
	if err != nil {
		return nil, err
	}
	return article, nil
}
